﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace TomcatTool
{
    internal class Catalina
    {
        /// <summary>
        /// tomcat进程
        /// </summary>
        private Process tomcatProcess = null;

        private string CURRENT_DIR = "";
        private string CATALINA_HOME = "";
        private string EXECUTABLE = "";
        public void Run(string path)
        {
            CURRENT_DIR = path;
            if (string.IsNullOrEmpty(path) || !Directory.Exists(path))
                CURRENT_DIR = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", ""));

            Console.WriteLine(CURRENT_DIR);
            CATALINA_HOME = CURRENT_DIR;
            if (!File.Exists(CATALINA_HOME + "\\bin\\tomcat9.exe"))
                CATALINA_HOME = new DirectoryInfo(CATALINA_HOME).Parent.FullName;
            EXECUTABLE = CATALINA_HOME + "\\bin\\tomcat9.exe";
            JAVA_HOME = GetJavaHome();
            Console.WriteLine(JAVA_HOME);
            if (File.Exists(EXECUTABLE))
            {
                RunTomcat(EXECUTABLE);
            }
        }
        private string CATALINA_BASE = "";
        private string JAVA_HOME = "";

        private string GetJavaHome()
        {
            string pathEnvironments = System.Environment.GetEnvironmentVariable("PATH");
            string[] paths = pathEnvironments.Split(';');
            foreach (string item in paths)
            {
                if (File.Exists(item + "\\java.exe"))
                    return item;
            }

            return null;
        }


        public void RunTomcat(string exeFile)
        {
            File.Delete(System.Environment.GetEnvironmentVariable("TEMP") + "\\catalina.bat.run");
            if (File.Exists(CURRENT_DIR + "\\tomcat9.exe"))
            {
                CATALINA_BASE = CATALINA_HOME;
                //set classpath
                if (File.Exists(CURRENT_DIR + "\\setenv.bat"))
                {
                    RunSetenv();
                }
                if (File.Exists(CURRENT_DIR + "\\setclasspath.bat"))
                {
                    RunSetClasspath();
                }
                string _EXECJAVA = JAVA_HOME + "\\java.exe";

                string LOGGING_CONFIG = CATALINA_HOME + "\\conf\\logging.properties";

                string CATALINA_TMPDIR = CATALINA_HOME + "\\temp";
                string CLASSPATH = string.Format("{0}\\bootstrap.jar;{0}\\tomcat-juli.jar", CURRENT_DIR);
                string paramFormat = "-Djava.util.logging.config.file=\"{0}\" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 " +
                    " -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs=\"\" -classpath \"{1}\" -Dcatalina.base=\"{2}\" -Dcatalina.home=\"{3}\" -Djava.io.tmpdir=\"{4}\" org.apache.catalina.startup.Bootstrap start";
                string param = string.Format(paramFormat, LOGGING_CONFIG, CLASSPATH, CATALINA_BASE, CATALINA_HOME, CATALINA_TMPDIR);

                //StringBuilder paramBuilder = new StringBuilder();
                //paramBuilder.AppendFormat("\"-Djava.util.logging.config.file={0}\" ", LOGGING_CONFIG);
                //paramBuilder.AppendFormat("\"-Djava.util.logging.manager={0}\" ", "org.apache.juli.ClassLoaderLogManager");
                //paramBuilder.AppendFormat("\"-Djdk.tls.ephemeralDHKeySize={0}\" ", 2048);
                //paramBuilder.AppendFormat("\"-Djava.protocol.handler.pkgs={0}\" ", LOGGING_CONFIG);
                //paramBuilder.AppendFormat("\"-Djava.util.logging.config.file={0}\" ", "org.apache.catalina.webresources");
                //paramBuilder.AppendFormat("\"-Dignore.endorsed.dirs={0}\" ", "");
                //paramBuilder.AppendFormat("\"-classpath\" \"{0}\" ", CLASSPATH);
                //paramBuilder.AppendFormat("\"-Dcatalina.base={0}\" ", CATALINA_BASE);
                //paramBuilder.AppendFormat("\"-Dcatalina.home={0}\" ", CATALINA_HOME);
                //paramBuilder.AppendFormat("\"-Djava.io.tmpdir={0}\" ", CATALINA_TMPDIR);
                //paramBuilder.AppendFormat("\"org.apache.catalina.startup.Bootstrap {0}\" ", "start");
                Console.WriteLine("java:" + _EXECJAVA);
                Console.WriteLine("param:" + param);
                Process process = new Process();
                //Console.WriteLine(paramBuilder.ToString());
                ProcessStartInfo startInfo = new ProcessStartInfo("\"" + _EXECJAVA + "\"", param)
                {
                    //WindowStyle = ProcessWindowStyle.Normal,
                    RedirectStandardInput = true,
                    //RedirectStandardError = true,
                    //CreateNoWindow = false,
                    //RedirectStandardOutput = true,
                    UseShellExecute = false
                };

                Console.WriteLine("startInfo:" + startInfo.FileName);
                process.StartInfo = startInfo;
                process.ErrorDataReceived += Process_ErrorDataReceived;
                process.OutputDataReceived += Process_OutputDataReceived;
                process.Start();
                //process.StandardInput.WriteLine("\"" + _EXECJAVA + "\" " + param);
                process.StandardInput.AutoFlush = true;
                process.StandardInput.WriteLine();
                System.Threading.Thread.Sleep(3000);
                process.StandardInput.WriteLine();
                tomcatProcess = process;
                Console.WriteLine(process.Id);
                Task.Factory.StartNew(new Action(() =>
                {
                    int num = 10;
                    while (true)
                    {
                        if (process.HasExited && num > 0)
                        {
                            num--;
                            Console.WriteLine("重启服务");
                            process.Start();
                            tomcatProcess = process;
                        }
                    }
                }));

            }
        }

        private void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            Console.WriteLine(e.Data);
        }

        private void WatchTomcatOut(Process process)
        {
            while (1 == 1)
            {
                try
                {
                    if (process.HasExited)
                        return;
                    string msg = process.StandardOutput.ReadLine();
                    if (!string.IsNullOrEmpty(msg))
                        Console.WriteLine("tomcat:" + msg);
                }
                catch (Exception ex)
                {
                    // Console.WriteLine(ex.Message);
                }
            }
        }
        private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            Console.WriteLine(e.Data);
        }

        public void RunSetenv()
        {

        }
        public void RunSetClasspath()
        {

        }
        public void Close()
        {
            try
            {
                if (tomcatProcess != null && !tomcatProcess.HasExited)
                {
                    tomcatProcess.Kill();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}
